﻿using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Interactivity;
using KinonekoSoftware.ArkSpark.Runtimes.Presenters;
using KinonekoSoftware.Extensions.Ioc;

namespace KinonekoSoftware.ArkSpark.LinuxUI.Styles
{
    public class TextBoxStatic : AvaloniaObject
    {
        public static readonly AttachedProperty<bool> AutoFocusProperty
            = AvaloniaProperty.RegisterAttached<TextBoxStatic, Interactive, bool>("AutoFocus",
                                                                                  false,
                                                                                  false,
                                                                                  BindingMode.OneTime);

        public static readonly AttachedProperty<bool> EnableHeadingTextProperty
            = AvaloniaProperty.RegisterAttached<TextBoxStatic, Interactive, bool>("EnableHeadingText",
                                                                                  false,
                                                                                  false,
                                                                                  BindingMode.OneTime);
        const int D1 = (int)Key.D1;
        const int D7 = (int)Key.D7;
        const int N1 = (int)Key.NumPad1;
        const int N7 = (int)Key.NumPad7;

        static TextBoxStatic()
        {
            AutoFocusProperty.Changed.AddClassHandler<Interactive>(HandleAutoFocusChanged);
        }
        
        
        private static void HandleAutoFocusChanged(Interactive interactElem, AvaloniaPropertyChangedEventArgs args)
        {
            if (args.Sender is not TextBox element)
            {
                return;
            }
            
            if (args.GetNewValue<bool>())
            {
                element.AttachedToVisualTree   += OnAttachedToVisualTree;
                element.DetachedFromVisualTree += OnDetachedFromVisualTree;
            }
            else
            {
                element.AttachedToVisualTree   -= OnAttachedToVisualTree;
                element.DetachedFromVisualTree -= OnDetachedFromVisualTree;
            }
        }
        
        public static void SetAutoFocus(AvaloniaObject element, bool value)
        {
            element.SetValue(AutoFocusProperty, value);
        }

        public static bool GetAutoFocus(AvaloniaObject element)
        {
            return element.GetValue(AutoFocusProperty);
        }
        
        
        public static void SetEnableHeadingText(TextBox element, bool value)
        {
            element.KeyUp    += OnKeyUp;
            element.Unloaded += OnUnloaded;
            element.SetValue(EnableHeadingTextProperty, value);
        }
        
        public static bool GetEnableHeadingText(TextBox element)
        {
            return element.GetValue(EnableHeadingTextProperty);
        }
        
        
        private static void OnKeyUp(object sender, KeyEventArgs e)
        {
            var keyNum = (int)e.Key;
            var level  = -1;

            if(e.KeyModifiers != KeyModifiers.Control)
            {
                return;
            }

            if (keyNum >= D1 && keyNum <= D7)
            {
                level = Math.Clamp(keyNum - D1 + 1, 1, 7);
            }

            if (keyNum >= N1 && keyNum <= N7)
            {
                level = Math.Clamp(keyNum - N1 + 1, 1, 7);
            }

            if(level < 0)
            {
                return;
            }

            if (sender is TextBox { DataContext: HeadingTextPresenter presenter })
            {
                presenter.Level = level;
                presenter.Update();
            }
        }

        private static void OnUnloaded(object sender, RoutedEventArgs e)
        {
            if (sender is TextBox editor)
            {
                editor.KeyUp    -= OnKeyUp;
                editor.Unloaded -= OnUnloaded;
            }
        }


        private static void OnDetachedFromVisualTree(object sender, VisualTreeAttachmentEventArgs e)
        {
            if (sender is TextBox editor)
            {
                editor.Focus(NavigationMethod.Tab);
            }
        }

        private static void OnAttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs e)
        {
            if (sender is TextBox editor)
            {
                editor.Focus();
            }
        }
    }
}